package cn.feizhu.aimarket.ai.utils;

import cn.feizhu.aimarket.model.dto.ai.outline.NovelOutlineResponse;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class JsonFixer {

    /**
     * 智能JSON修复器 - 主入口方法
     *
     * @param jsonString 待修复的JSON字符串
     * @param targetClass 目标类型
     * @return 修复后的对象
     */
    public static <T> T smartJsonFixer(String jsonString, Class<T> targetClass) {
        try {
            // 1. 预处理JSON字符串
            String cleanedJson = preprocessJson(jsonString);

            // 2. 尝试直接解析
            if(JsonToObjectValidator.canConvertToObject(cleanedJson, targetClass)) {
                return JSONUtil.toBean(cleanedJson, targetClass);
            }

            System.out.println("直接解析失败，开始智能修复");

            // 3. 智能修复
            String fixedJson = intelligentJsonFix(cleanedJson, targetClass);

            // 4. 再次尝试解析
             return JSONUtil.toBean(fixedJson, targetClass);

        } catch (Exception e) {
            throw new RuntimeException("JSON修复失败: " + e.getMessage(), e);
        }
    }

    /**
     * JSON字符串预处理 - 清理和格式化
     */
    private static String preprocessJson(String jsonString) {
        if (jsonString == null || jsonString.trim().isEmpty()) {
            return "{}";
        }

        String cleaned = jsonString.trim();

        // 移除可能的markdown标记
        cleaned = cleaned.replaceAll("^```json\\s*", "").replaceAll("\\s*```$", "");
        cleaned = cleaned.replaceAll("^```\\s*", "").replaceAll("\\s*```$", "");

        // 修复常见的括号问题
        cleaned = fixBrackets(cleaned);

        // 修复引号问题
        cleaned = fixQuotes(cleaned);

        // 移除多余的逗号
        cleaned = removeExtraCommas(cleaned);

        return cleaned;
    }

    /**
     * 修复括号匹配问题
     */
    private static String fixBrackets(String json) {
        Stack<Character> stack = new Stack<>();
        StringBuilder result = new StringBuilder();

        for (char c : json.toCharArray()) {
            if (c == '{' || c == '[') {
                stack.push(c);
                result.append(c);
            } else if (c == '}' || c == ']') {
                if (!stack.isEmpty()) {
                    char expected = (c == '}') ? '{' : '[';
                    if (stack.peek() == expected) {
                        stack.pop();
                        result.append(c);
                    } else {
                        // 括号不匹配，尝试修复
                        while (!stack.isEmpty() && stack.peek() != expected) {
                            char missing = (stack.pop() == '{') ? '}' : ']';
                            result.append(missing);
                        }
                        if (!stack.isEmpty()) {
                            stack.pop();
                        }
                        result.append(c);
                    }
                } else {
                    // 多余的右括号，忽略
                }
            } else {
                result.append(c);
            }
        }

        // 补充缺失的右括号
        while (!stack.isEmpty()) {
            char missing = (stack.pop() == '{') ? '}' : ']';
            result.append(missing);
        }

        return result.toString();
    }

    /**
     * 修复引号问题
     */
    private static String fixQuotes(String json) {
        // 修复字段名缺少引号的问题
        Pattern pattern = Pattern.compile("([{,]\\s*)([a-zA-Z_][a-zA-Z0-9_]*)\\s*:");
        Matcher matcher = pattern.matcher(json);
        StringBuffer sb = new StringBuffer();

        while (matcher.find()) {
            String prefix = matcher.group(1);
            String fieldName = matcher.group(2);
            matcher.appendReplacement(sb, prefix + "\"" + fieldName + "\":");
        }
        matcher.appendTail(sb);

        return sb.toString();
    }

    /**
     * 移除多余的逗号
     */
    private static String removeExtraCommas(String json) {
        // 移除对象或数组结束前的多余逗号
        json = json.replaceAll(",\\s*([}\\]])", "$1");
        // 移除连续的逗号
        json = json.replaceAll(",\\s*,", ",");
        return json;
    }

    /**
     * 智能JSON修复 - 核心算法
     */
    private static String intelligentJsonFix(String jsonString, Class<?> targetClass) {
        try {
            // 1. 提取目标类的字段信息
            Map<String, FieldInfo> targetFields = extractClassFields(targetClass);

            // 2. 解析原始JSON获取数据
            Map<String, Object> sourceData = parseJsonToMap(jsonString);

            // 3. 智能字段匹配和重构
            Map<String, Object> fixedData = reconstructJson(sourceData, targetFields);

            // 4. 转换为JSON字符串
            return JSONUtil.toJsonPrettyStr(fixedData);

        } catch (Exception e) {
            throw new RuntimeException("智能修复失败: " + e.getMessage(), e);
        }
    }

    /**
     * 提取类的字段信息
     */
    private static Map<String, FieldInfo> extractClassFields(Class<?> clazz) {
        Map<String, FieldInfo> fields = new HashMap<>();

        for (Field field : clazz.getDeclaredFields()) {
            if (field.getName().equals("serialVersionUID")) {
                continue;
            }

            FieldInfo fieldInfo = new FieldInfo();
            fieldInfo.name = field.getName();
            fieldInfo.type = field.getType();
            fieldInfo.genericType = field.getGenericType();

            fields.put(field.getName().toLowerCase(), fieldInfo);
        }

        return fields;
    }

    /**
     * 解析JSON为Map，容错性强
     */
    private static Map<String, Object> parseJsonToMap(String jsonString) {
        try {
            return JSONUtil.parseObj(jsonString);
        } catch (Exception e) {
            // 如果解析失败，尝试手动提取键值对
            return extractKeyValuePairs(jsonString);
        }
    }

    /**
     * 手动提取键值对（容错性解析）
     */
    private static Map<String, Object> extractKeyValuePairs(String jsonString) {
        Map<String, Object> result = new HashMap<>();

        // 使用正则表达式提取键值对
        Pattern pattern = Pattern.compile("\"([^\"]+)\"\\s*:\\s*([^,}\\]]+|\\[[^\\]]*\\]|\\{[^}]*\\})");
        Matcher matcher = pattern.matcher(jsonString);

        while (matcher.find()) {
            String key = matcher.group(1);
            String value = matcher.group(2).trim();

            // 解析值
            Object parsedValue = parseValue(value);
            result.put(key, parsedValue);
        }

        return result;
    }

    /**
     * 解析单个值
     */
    private static Object parseValue(String value) {
        value = value.trim();

        if (value.startsWith("\"") && value.endsWith("\"")) {
            return value.substring(1, value.length() - 1);
        } else if (value.equals("null")) {
            return null;
        } else if (value.equals("true") || value.equals("false")) {
            return Boolean.parseBoolean(value);
        } else if (value.matches("-?\\d+")) {
            return Integer.parseInt(value);
        } else if (value.startsWith("[") && value.endsWith("]")) {
            // 简单数组解析
            String arrayContent = value.substring(1, value.length() - 1);
            if (arrayContent.trim().isEmpty()) {
                return new ArrayList<>();
            }
            String[] items = arrayContent.split(",");
            List<Object> list = new ArrayList<>();
            for (String item : items) {
                list.add(parseValue(item.trim()));
            }
            return list;
        } else if (value.startsWith("{") && value.endsWith("}")) {
            // 嵌套对象
            return parseJsonToMap(value);
        } else {
            return value;
        }
    }

    /**
     * 重构JSON数据
     */
    private static Map<String, Object> reconstructJson(Map<String, Object> sourceData, Map<String, FieldInfo> targetFields) {
        Map<String, Object> result = new HashMap<>();

        // 为每个目标字段寻找匹配的源数据
        for (Map.Entry<String, FieldInfo> entry : targetFields.entrySet()) {
            String targetFieldKey = entry.getKey();
            FieldInfo fieldInfo = entry.getValue();

            // 寻找最匹配的源字段
            String bestMatch = findBestFieldMatch(targetFieldKey, sourceData.keySet());

            if (bestMatch != null) {
                Object value = sourceData.get(bestMatch);

                // 类型转换和验证
                Object convertedValue = convertValue(value, fieldInfo);
                result.put(fieldInfo.name, convertedValue);
            } else {
                // 设置默认值
                result.put(fieldInfo.name, getDefaultValue(fieldInfo));
            }
        }

        return result;
    }

    /**
     * 字段名匹配算法 - 使用编辑距离和相似度
     */
    private static String findBestFieldMatch(String target, Set<String> candidates) {
        String bestMatch = null;
        double bestScore = 0.0;

        for (String candidate : candidates) {
            double score = calculateSimilarity(target, candidate.toLowerCase());
            if (score > bestScore && score > 0.6) { // 相似度阈值
                bestScore = score;
                bestMatch = candidate;
            }
        }

        return bestMatch;
    }

    /**
     * 计算字符串相似度
     */
    private static double calculateSimilarity(String s1, String s2) {
        if (s1.equals(s2)) {
            return 1.0;
        }

        int maxLen = Math.max(s1.length(), s2.length());
        if (maxLen == 0) {
            return 1.0;
        }

        int editDistance = levenshteinDistance(s1, s2);
        return 1.0 - (double) editDistance / maxLen;
    }

    /**
     * 计算编辑距离
     */
    private static int levenshteinDistance(String s1, String s2) {
        int[][] dp = new int[s1.length() + 1][s2.length() + 1];

        for (int i = 0; i <= s1.length(); i++) {
            dp[i][0] = i;
        }
        for (int j = 0; j <= s2.length(); j++) {
            dp[0][j] = j;
        }

        for (int i = 1; i <= s1.length(); i++) {
            for (int j = 1; j <= s2.length(); j++) {
                if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
                    dp[i][j] = dp[i - 1][j - 1];
                } else {
                    dp[i][j] = Math.min(Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;
                }
            }
        }

        return dp[s1.length()][s2.length()];
    }

    /**
     * 值类型转换
     */
    private static Object convertValue(Object value, FieldInfo fieldInfo) {
        if (value == null) {
            return getDefaultValue(fieldInfo);
        }

        Class<?> targetType = fieldInfo.type;

        // 基本类型转换
        if (targetType == String.class) {
            return value.toString();
        } else if (targetType == Integer.class || targetType == int.class) {
            if (value instanceof Number) {
                return ((Number) value).intValue();
            } else {
                try {
                    return Integer.parseInt(value.toString());
                } catch (NumberFormatException e) {
                    return 0;
                }
            }
        } else if (targetType == List.class) {
            if (value instanceof List) {
                return convertList((List<?>) value, fieldInfo);
            } else {
                return new ArrayList<>();
            }
        } else if (targetType.isAssignableFrom(Map.class) || isCustomClass(targetType)) {
            if (value instanceof Map) {
                return convertNestedObject((Map<String, Object>) value, targetType);
            } else {
                return createDefaultObject(targetType);
            }
        }

        return value;
    }

    /**
     * 转换List类型
     */
    private static List<?> convertList(List<?> sourceList, FieldInfo fieldInfo) {
        if (fieldInfo.genericType instanceof ParameterizedType) {
            ParameterizedType paramType = (ParameterizedType) fieldInfo.genericType;
            Type[] actualTypes = paramType.getActualTypeArguments();

            if (actualTypes.length > 0 && actualTypes[0] instanceof Class) {
                Class<?> elementType = (Class<?>) actualTypes[0];

                return sourceList.stream()
                    .map(item -> {
                        if (item instanceof Map && isCustomClass(elementType)) {
                            return convertNestedObject((Map<String, Object>) item, elementType);
                        } else {
                            return item;
                        }
                    })
                    .collect(Collectors.toList());
            }
        }

        return new ArrayList<>(sourceList);
    }

    /**
     * 转换嵌套对象
     */
    private static Object convertNestedObject(Map<String, Object> sourceMap, Class<?> targetType) {
        try {
            Map<String, FieldInfo> nestedFields = extractClassFields(targetType);
            Map<String, Object> convertedMap = reconstructJson(sourceMap, nestedFields);

            // 使用Jackson进行最终转换
            ObjectMapper mapper = new ObjectMapper();
            return mapper.convertValue(convertedMap, targetType);
        } catch (Exception e) {
            return createDefaultObject(targetType);
        }
    }

    /**
     * 判断是否为自定义类
     */
    private static boolean isCustomClass(Class<?> clazz) {
        return !clazz.isPrimitive() &&
               !clazz.getName().startsWith("java.") &&
               !clazz.getName().startsWith("javax.");
    }

    /**
     * 获取默认值
     */
    private static Object getDefaultValue(FieldInfo fieldInfo) {
        Class<?> type = fieldInfo.type;

        if (type == String.class) {
            return "";
        } else if (type == Integer.class || type == int.class) {
            return 0;
        } else if (type == Boolean.class || type == boolean.class) {
            return false;
        } else if (type == List.class) {
            return new ArrayList<>();
        } else if (type.isAssignableFrom(Map.class)) {
            return new HashMap<>();
        } else {
            return createDefaultObject(type);
        }
    }

    /**
     * 创建默认对象
     */
    private static Object createDefaultObject(Class<?> clazz) {
        try {
            return clazz.getDeclaredConstructor().newInstance();
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 字段信息类
     */
    private static class FieldInfo {
        String name;
        Class<?> type;
        Type genericType;
    }

    /**
     * 测试方法
     */
    public static void main(String[] args) {
        // 测试用例1：正常JSON
        String correctJson = """
            {
              "overview": {
                "theme": "故事主题描述",
                "coreCharacters": "核心人物详细描述",
                "coreScenes": "核心场景详细描述",
                "ruleSystemOverview": "整体规则体系概述",
                "styleDescription": "故事风格定位"
              },
              "totalChapters": 2,
              "chapters": [
                {
                  "chapterNumber": 1,
                  "title": "章节标题",
                  "plotSummary": "情节梗概描述",
                  "coreRule": "本章核心规则",
                  "horrorHook": "细思极恐的钩子",
                  "atmosphereType": "核心氛围类型",
                  "keyHorrorDetails": [
                    "关键恐怖细节1",
                    "关键恐怖细节2",
                    "关键恐怖细节3"
                  ],
                  "estimatedWordCount": "3000-3500字",
                  "horrorEscalationLevel": "恐怖升级位置",
                  "newRulesOrClues": "本章明确揭示的规则或线索",
                  "hiddenForeshadowing": "本章埋下的深层伏笔"
                }
              ]
            }
            """;

        // 测试用例2：有问题的JSON（模拟AI生成的错误）
        String failJson = """
            {
              "overview": {
                "theme": "在看似熟悉的日常中，时间与记忆被扭曲",
                "coreCharacters": "熊大：理性谨慎，善于观察细节",
                "coreScenes": "狗熊岭终日被灰白迷雾笼罩",
                "ruleSystemOverview": "森林存在一套隐形守则",
                "styleDescription": "微恐怖 × 规则怪谈"
              },
              "totalChapters": 7,
              "chapters": [
                {
                  "chapterNumber": 1,
                  "title": "又是1月10日",
                  "plotSummary": "熊大清晨醒来，发现日历再次停在1月10日",
                  "coreRule": "如果你的日历没有翻页，不要尝试撕掉它",
                  "horrorHook": "熊二吃完蜂蜜后，嘴角残留的金色液体缓缓流回嘴里",
                  "atmosphereType": "静压型",
                  "keyHorrorDetails": [
                    "日历纸张边缘有被反复撕过的毛边",
                    "熊二舔手指时，蜂蜜像是从空气中凝结出来"
                  ],
                  "estimatedWordCount": "3000-3500字",
                  "horrorEscalationLevel": "初显异样",
                  "newRulesOrClues": "日历不会翻页意味着时间循环",
                  "hiddenForeshadowing": "光头强背包里露出一角写满'第47次'的笔记本"
                }
              ]
            }
            """;

        try {
            System.out.println("=== 测试正常JSON ===");
            NovelOutlineResponse result1 = smartJsonFixer(correctJson, NovelOutlineResponse.class);
            System.out.println("解析成功: " + result1.getOverview().getTheme());
            System.out.println("章节数: " + result1.getTotalChapters());
            System.out.println("实际章节数: " + result1.getChapters().size());

            System.out.println("\n=== 测试问题JSON ===");
            NovelOutlineResponse result2 = smartJsonFixer(failJson, NovelOutlineResponse.class);
            System.out.println("修复成功: " + result2.getOverview().getTheme());
            System.out.println("章节数: " + result2.getTotalChapters());
            System.out.println("实际章节数: " + result2.getChapters().size());

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
